package org.qtmo.emu.nes;
import flash.utils.ByteArray;
import org.qtmo.emu.nes.mapper.Mapper;
import org.qtmo.emu.nes.mapper.Mapper00;

/**
 * ...
 * @author Sang Hua Cai
 */

class ROM
{
	public var mapper:Mapper;
	public var header:NESHeader;

	public function new(nes:NES)
	{
		this.nes = nes;

		header = new NESHeader();
	}

	public function InsertCartridge(rom:ByteArray):Void
	{
		header.ReadHead(rom);

		var size:UInt = rom.bytesAvailable;
		for (i in HEADER_SIZE...size)
		{
			MMU.Write(i - HEADER_SIZE + MMU.ROM_OFFSET, rom[i]);
		}
		trace("org.qtmo.emu.nes.mapper.Mapper" + StringTools.hex(header.MAPPER, 2));
		mapper = Type.createInstance(Type.resolveClass("org.qtmo.emu.nes.mapper.Mapper" + StringTools.hex(header.MAPPER, 2)), [this.nes]);
	}

	private var nes:NES;

	private static inline var HEADER_SIZE:UInt = 0x10;
}

/*
A. iNES Format (.NES)
---------------------
+--------+------+------------------------------------------+
| Offset | Size | Content(s)                               |
+--------+------+------------------------------------------+
|   0    |  3   | 'NES'                                    |
|   3    |  1   | $1A                                      |
|   4    |  1   | 16K PRG-ROM page count                   |
|   5    |  1   |  8K CHR-ROM page count                   |
|   6    |  1   | ROM Control Byte #1                      |
|        |      |   %####vTsM                              |
|        |      |    |  ||||+- 0=Horizontal mirroring      |
|        |      |    |  ||||   1=Vertical mirroring        |
|        |      |    |  |||+-- 1=SRAM enabled              |
|        |      |    |  ||+--- 1=512-byte trainer present  |
|        |      |    |  |+---- 1=Four-screen mirroring     |
|        |      |    |  |                                  |
|        |      |    +--+----- Mapper # (lower 4-bits)     |
|   7    |  1   | ROM Control Byte #2                      |
|        |      |   %####00PV                              |
|        |      |    |  |  |+- 1=VS-Unisystem Images       |
|        |      |    |  |  +-- 1=PlayChoice10 Images       |
|        |      |    |  |                                  |
|        |      |    +--+----- Mapper # (upper 4-bits)     |
|  8-15  |  8   | $00                                      |
| 16-..  |      | Actual 16K PRG-ROM pages (in linear      |
|  ...   |      | order). If a trainer exists, it precedes |
|  ...   |      | the first PRG-ROM page.                  |
| ..-EOF |      | CHR-ROM pages (in ascending order).      |
+--------+------+------------------------------------------+
*/
class NESHeader
{
	public var PRG_PAGE_SIZE:UInt;
	public var CHR_PAGE_SIZE:UInt;
	public var IsVMIRROR:Bool;
	public var Is4SCREEN:Bool;
	public var IsSAVERAM:Bool;
	public var IsTRAINER:Bool;
	public var MAPPER:UInt;

	public function new()
	{

	}

	public function ReadHead(rom:ByteArray):Bool
	{
		if (rom[0] != 0x4E || rom[1] != 0x45 || rom[2] != 0x53 || rom[3] != 0x1A)
		{
			trace('invalid Nes file');
			return false;
		}
		PRG_PAGE_SIZE = rom[4];
		CHR_PAGE_SIZE = rom[5];

		IsVMIRROR = rom[6] & ROM_VMIRROR > 0;
		IsSAVERAM = rom[6] & ROM_SAVERAM > 0;
		IsTRAINER = rom[6] & ROM_TRAINER > 0;
		Is4SCREEN = rom[6] & ROM_4SCREEN > 0;

		MAPPER = (rom[6] & 0xF0) >> 4;
		MAPPER |= (rom[7] & 0xF0);

		return true;
	}

	private static inline var ROM_VMIRROR:UInt = 0x01;
	private static inline var ROM_SAVERAM:UInt = 0x02;
	private static inline var ROM_TRAINER:UInt = 0x04;
	private static inline var ROM_4SCREEN:UInt = 0x08;
}
/*
class NSFHEADER
{
public var	ID[5];
public var	Version;
public var	TotalSong;
public var	StartSong;
public var	LoadAddress;
public var	InitAddress;
public var	PlayAddress;
public var	SongName[32];
public var	ArtistName[32];
public var	CopyrightName[32];
public var	SpeedNTSC;
public var	BankSwitch[8];
public var	SpeedPAL;
public var	NTSC_PALbits;
public var	ExtraChipSelect;
public var	Expansion[4];
}*/
